#ifndef _ACTION_H_
#define _ACTION_H_

#include <memory>
#include <iostream>
#include <functional>
#include "Event.h"
#include "State.h"
#include "Transition.h"
#include "Context.h"

class Action{
public:
    Action(std::shared_ptr<Transition> transition): m_transition(transition)
    {}

    Action(int curState, int nextState){
        m_transition = std::make_shared<Transition>(curState, nextState);
    }
    Action(int curState, int nextState, std::function<bool(std::shared_ptr<Context>)>& func){
        m_transition = std::make_shared<Transition>(curState, nextState, func);
    }

    virtual std::shared_ptr<State> Execute(std::shared_ptr<State> state, std::shared_ptr<Event> event, std::shared_ptr<Context> context = NULL){
        return NULL;
    };
public:
    std::shared_ptr<Transition> m_transition;
};

// 对应 PressEnterGameBtn事件
class EnterGameAction: public Action{
public:
    EnterGameAction(int curState, int nextState): Action(curState, nextState){}
    virtual std::shared_ptr<State> Execute(std::shared_ptr<State> state, std::shared_ptr<Event> event, std::shared_ptr<Context> context = NULL)
    {   
        // EnterGameAction 特别操作 TODO
        std::shared_ptr<State> nextState = std::make_shared<UserState>(m_transition->m_nextState);
        if(context != NULL && m_transition->m_satisfiedFun != NULL && !m_transition->m_satisfiedFun(context))
        {
            nextState = std::make_shared<UserState>(m_transition->m_curState);
        } 
        
        auto userEvent = std::static_pointer_cast<UserEvent>(event);
        std::cout << userEvent->m_userName << " " << event->GetEventActionName() << ", 玩家状态从 " << state->GetString() << " 到 " << nextState->GetString() << std::endl;
        return nextState;
    }
};

// 对应 PressLeaveGameBtn事件
class LeaveGameAction: public Action{
public:
    LeaveGameAction(int curState, int nextState): Action(curState, nextState){}
    virtual std::shared_ptr<State> Execute(std::shared_ptr<State> state, std::shared_ptr<Event> event, std::shared_ptr<Context> context = NULL)
    {   
        // LeaveGameAction 特别操作 TODO
        std::shared_ptr<State> nextState = std::make_shared<UserState>(m_transition->m_nextState);
        if(context != NULL && m_transition->m_satisfiedFun != NULL && !m_transition->m_satisfiedFun(context))
        {
            nextState = std::make_shared<UserState>(m_transition->m_curState);
        } 
        
        auto userEvent = std::static_pointer_cast<UserEvent>(event);
        std::cout << userEvent->m_userName << " " << event->GetEventActionName() << ", 玩家状态从 " << state->GetString() << " 到 " << nextState->GetString() << std::endl;
        return nextState;
    }
};

// 对应 PressEnterGameRoom201Btn事件
class EnterGameRoom201Action: public Action{
public:
    EnterGameRoom201Action(int curState, int nextState): Action(curState, nextState){}
    virtual std::shared_ptr<State> Execute(std::shared_ptr<State> state, std::shared_ptr<Event> event, std::shared_ptr<Context> context = NULL)
    {   
        // EnterGameRoom201Action 特别操作 TODO
        std::shared_ptr<State> nextState = std::make_shared<UserState>(m_transition->m_nextState);
        if(context != NULL && m_transition->m_satisfiedFun != NULL && !m_transition->m_satisfiedFun(context))
        {
            nextState = std::make_shared<UserState>(m_transition->m_curState);
        } 
        
        auto userEvent = std::static_pointer_cast<UserEvent>(event);
        std::cout << userEvent->m_userName << " " << event->GetEventActionName() << ", 玩家状态从 " << state->GetString() << " 到 " << nextState->GetString() << std::endl;
        return nextState;
    }
};

// 对应 PressEnterGameRoom202Btn事件
class EnterGameRoom202Action: public Action{ //
public:
    EnterGameRoom202Action(int curState, int nextState): Action(curState, nextState){}
    virtual std::shared_ptr<State> Execute(std::shared_ptr<State> state, std::shared_ptr<Event> event, std::shared_ptr<Context> context = NULL)
    {   
        // EnterGameRoom202Action 特别操作 TODO
        std::shared_ptr<State> nextState = std::make_shared<UserState>(m_transition->m_nextState);
        if(context != NULL && m_transition->m_satisfiedFun != NULL && !m_transition->m_satisfiedFun(context))
        {
            nextState = std::make_shared<UserState>(m_transition->m_curState);
        } 
        
        auto userEvent = std::static_pointer_cast<UserEvent>(event);
        std::cout << userEvent->m_userName << " " << event->GetEventActionName() << ", 玩家状态从 " << state->GetString() << " 到 " << nextState->GetString() << std::endl;
        return nextState;
    }
};

// 对应 PressLeaveGameRoom201Btn事件
class LeaveGameRoom201Action: public Action{
public:
    LeaveGameRoom201Action(int curState, int nextState): Action(curState, nextState){}
    virtual std::shared_ptr<State> Execute(std::shared_ptr<State> state, std::shared_ptr<Event> event, std::shared_ptr<Context> context = NULL)
    {   
        // LeaveGameRoom201Action 特别操作 TODO
        std::shared_ptr<State> nextState = std::make_shared<UserState>(m_transition->m_nextState);
        if(context != NULL && m_transition->m_satisfiedFun != NULL && !m_transition->m_satisfiedFun(context))
        {
            nextState = std::make_shared<UserState>(m_transition->m_curState);
        } 
        
        auto userEvent = std::static_pointer_cast<UserEvent>(event);
        std::cout << userEvent->m_userName << " " << event->GetEventActionName() << ", 玩家状态从 " << state->GetString() << " 到 " << nextState->GetString() << std::endl;
        return nextState;
    }
};

// 对应 PressLeaveGameRoom202Btn事件
class LeaveGameRoom202Action: public Action{
public:
    LeaveGameRoom202Action(int curState, int nextState): Action(curState, nextState){}
    virtual std::shared_ptr<State> Execute(std::shared_ptr<State> state, std::shared_ptr<Event> event, std::shared_ptr<Context> context = NULL)
    {   
        // LeaveGameRoom202Action 特别操作 TODO
        std::shared_ptr<State> nextState = std::make_shared<UserState>(m_transition->m_nextState);
        if(context != NULL && m_transition->m_satisfiedFun != NULL && !m_transition->m_satisfiedFun(context))
        {
            nextState = std::make_shared<UserState>(m_transition->m_curState);
        } 
        
        auto userEvent = std::static_pointer_cast<UserEvent>(event);
        std::cout << userEvent->m_userName << " " << event->GetEventActionName() << ", 玩家状态从 " << state->GetString() << " 到 " << nextState->GetString() << std::endl;
        return nextState;
    }
};

// 对应 PressEnterGameRoom201Btn事件 和  PressEnterGameRoom202Btn事件
class Room_EnterGameRoomAction: public Action {
public:
    Room_EnterGameRoomAction(int curState, int nextState, std::function<bool(std::shared_ptr<Context>)>& func): Action(curState, nextState, func){}
    virtual std::shared_ptr<State> Execute(std::shared_ptr<State> state, std::shared_ptr<Event> event, std::shared_ptr<Context> context = NULL)
    {   
        // Room_EnterGameRoomAction 特别操作 TODO
        std::shared_ptr<State> nextState = std::make_shared<RoomState>(m_transition->m_nextState);
        if(context != NULL && m_transition->m_satisfiedFun != NULL && !m_transition->m_satisfiedFun(context))
        {
            nextState = std::make_shared<RoomState>(m_transition->m_curState);
        } 
        
        auto roomEvent = std::static_pointer_cast<RoomEvent>(event);
        std::cout << roomEvent->m_roomName << " 从 " << state->GetString() << " 到 " << nextState->GetString() << std::endl;
        return nextState;
    }
};

// 对应 LeaveGameRoom201Action事件 和  LeaveGameRoom202Action事件
class Room_LeaveGameRoomAction: public Action {
public:
    Room_LeaveGameRoomAction(int curState, int nextState, std::function<bool(std::shared_ptr<Context>)>& func): Action(curState, nextState, func){}
    virtual std::shared_ptr<State> Execute(std::shared_ptr<State> state, std::shared_ptr<Event> event, std::shared_ptr<Context> context = NULL)
    {   
        // Room_LeaveGameRoomAction 特别操作 TODO
        std::shared_ptr<State> nextState = std::make_shared<RoomState>(m_transition->m_nextState);
        if(context != NULL && m_transition->m_satisfiedFun != NULL && !m_transition->m_satisfiedFun(context))
        {
            nextState = std::make_shared<RoomState>(m_transition->m_curState);
        } 

        auto roomEvent = std::static_pointer_cast<RoomEvent>(event);
        std::cout << roomEvent->m_roomName << " 从 " << state->GetString() << " 到 " << nextState->GetString() << std::endl;
        return nextState;
    }
};

#endif